#include "SerialPort.h"
#include <QSerialPortInfo>
#include <QDebug>
#include "common/logger.h"

SerialPort::SerialPort(QObject *parent)
    : QObject(parent),
    m_serialPort(new QSerialPort(this))   // 在初始化列表中初始化 m_serialPort
{
    connect(m_serialPort, &QSerialPort::readyRead, [this]() {
        QByteArray data = m_serialPort->readAll();
        emit dataReceived(data);  // 接收到数据时触发信号
    });

    connect(m_serialPort, &QSerialPort::errorOccurred, [this](QSerialPort::SerialPortError error) {
        if (error != QSerialPort::NoError) {
            emit errorOccurred(m_serialPort->errorString());  // 发生错误时触发信号
        }
    });
}

SerialPort::~SerialPort()
{
    if (m_serialPort->isOpen()) {
        m_serialPort->close();  // 在析构时关闭串口
    }
}

bool SerialPort::isConnected() const
{
    return m_serialPort->isOpen();
}

QStringList SerialPort::availablePorts()
{
    m_availablePorts.clear();  // 清空现有的端口列表
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        m_availablePorts.append(info.portName());  // 添加可用端口
    }
    emit availablePortsChanged();  // 端口列表发生变化时发射信号
    return m_availablePorts;
}

// 连接端口
bool SerialPort::connectToPort(const QString &portName, int baudRate, int dataBits, int parity, int  stopBits)
{
    // 记录连接尝试的时间和目标端口信息
    QString logMessage = QString("Attempting to connect to port: %1 at baud rate: %2, data bits: %3, parity: %4, stop bits: %5")
                             .arg(portName)
                             .arg(baudRate)
                             .arg(dataBits)
                             .arg(parity)
                             .arg(stopBits);
    Logger::log(UART_LOG_FILE, logMessage);  // 记录连接尝试的日志

    if (m_serialPort->isOpen()) {
        m_serialPort->close();  // 如果串口已经打开，则关闭
        logMessage = QString("Port %1 was already open. Closing the port.").arg(portName);
        Logger::log(UART_LOG_FILE, logMessage);  // 记录端口已经打开并关闭的日志
    }

    m_serialPort->setPortName(portName);
    m_serialPort->setBaudRate(baudRate);

    // 选择数据位
    switch(dataBits)
    {
        case 5:m_serialPort->setDataBits(QSerialPort::Data5);break;
        case 6:m_serialPort->setDataBits(QSerialPort::Data6);break;
        case 7:m_serialPort->setDataBits(QSerialPort::Data7);break;
        case 8:m_serialPort->setDataBits(QSerialPort::Data8);break;
        default: m_serialPort->setDataBits(QSerialPort::UnknownDataBits);break;
    }

    // 选择校验位
    switch(parity)
    {
        case 0: m_serialPort->setParity(QSerialPort::NoParity);break;
        case 1: m_serialPort->setParity(QSerialPort::EvenParity);break;
        case 2: m_serialPort->setParity(QSerialPort::OddParity);break;
        case 3: m_serialPort->setParity(QSerialPort::SpaceParity);break;
        case 4: m_serialPort->setParity(QSerialPort::MarkParity);break;
        default: m_serialPort->setParity(QSerialPort::UnknownParity);break;
    }

    // 选择停止位
    switch(stopBits)
    {
        case 0:m_serialPort->setStopBits(QSerialPort::OneStop);break;
        case 1:m_serialPort->setStopBits(QSerialPort::OneAndHalfStop);break;
        case 2:m_serialPort->setStopBits(QSerialPort::TwoStop);break;
        default: m_serialPort->setStopBits(QSerialPort::UnknownStopBits);break;
    }

    m_serialPort->setFlowControl(QSerialPort::NoFlowControl);  // 设置流控制

    if (m_serialPort->open(QIODevice::ReadWrite)) {
        emit isConnectedChanged();  // 连接成功时发射信号
        logMessage = QString("Successfully connected to port: %1 at baud rate: %2").arg(portName).arg(baudRate);
        Logger::log(UART_LOG_FILE, logMessage);  // 记录连接成功的日志
        return true;  // 返回成功标志
    } else {
        // 如果连接失败，记录失败原因
        QString errorMsg = m_serialPort->errorString();
        emit errorOccurred(errorMsg);  // 打开串口失败时发射错误信号

        logMessage = QString("Failed to connect to port: %1. Error: %2").arg(portName).arg(errorMsg);
        Logger::log(UART_LOG_FILE, logMessage);  // 记录连接失败的日志

        // 如果有特定的错误类型（例如权限问题），可以进一步处理
        if (m_serialPort->error() == QSerialPort::PermissionError) {
            logMessage = QString("Permission error while trying to open port: %1.").arg(portName);
            Logger::log(UART_LOG_FILE, logMessage);
        } else if (m_serialPort->error() == QSerialPort::OpenError) {
            logMessage = QString("Open error while trying to open port: %1.").arg(portName);
            Logger::log(UART_LOG_FILE, logMessage);
        }

        return false;  // 返回失败标志
    }
}


void SerialPort::disconnectPort()
{
    if (m_serialPort->isOpen()) {
        m_serialPort->close();  // 断开连接
        emit isConnectedChanged();  // 发射连接状态改变信号
    }
}

void SerialPort::sendData(const QByteArray &data)
{
    // 记录尝试发送数据的时间和数据大小
    QString logMessage = QString("Attempting to send %1 bytes of data").arg(data.size());
    Logger::log(UART_LOG_FILE, logMessage);  // 记录发送数据尝试的日志

    if (m_serialPort->isOpen()) {
        qint64 bytesWritten = m_serialPort->write(data);  // 发送数据

        if (bytesWritten == -1) {
            // 记录写入数据失败的错误信息
            QString errorMsg = m_serialPort->errorString();
            logMessage = QString("Failed to send data. Error: %1").arg(errorMsg);
            Logger::log(UART_LOG_FILE, logMessage);  // 记录写入失败的日志
            emit errorOccurred(errorMsg);  // 发射错误信号
        } else {
            // 记录成功发送的数据字节数
            logMessage = QString("Successfully sent %1 bytes of data").arg(bytesWritten);
            Logger::log(UART_LOG_FILE, logMessage);  // 记录发送成功的日志
        }
    } else {
        // 如果串口未打开，记录错误信息
        QString errorMsg = "Port is not open.";
        logMessage = QString("Failed to send data. Error: %1").arg(errorMsg);
        Logger::log(UART_LOG_FILE, logMessage);  // 记录串口未打开的错误日志
        emit errorOccurred(errorMsg);  // 发射错误信号
    }
}

